'''
s7 客户端
pip install python-snap7
pip install python-snap7[cli]
https://blog.csdn.net/pista/article/details/113405915
启动模拟服务端命令 snap7-server
'''

import snap7
from snap7 import util
try:
    from plc_client.layer1.abc_client import PLCClientInterface
except:
    from abc_client import PLCClientInterface
# 绝对地址通讯； 标签通讯方式


class S7Client(PLCClientInterface):

    def __init__(self, ip='127.0.0.1', port=1102, dbnumber=183):
        # 创建通讯客户端实例
        self.client = snap7.client.Client()
        self.ip = ip
        self.port = port
        self.dbnumber = dbnumber

    def connect(self):
        # 连接至PLC
        try:
            self.client.connect(self.ip, 0, 0, self.port)  # 请求大小为480B的pdu
        except Exception as e:
            print('xxx')
            print(e)
        print(f"客户端 是否连接到 plc服务端：{self.client.get_connected()}")

    def get_connected(self):
        return self.client.get_connected()

    def read_int8(self, start=0, size=1) -> int:
        buffer = self.client.read_area(snap7.types.Areas.DB, self.dbnumber, start, size)  # buffer为bytearray
        value_int8 = util.get_byte(buffer,0) # uint8
        return value_int8

    def read_int16(self, start=0, size=2) -> int:  # 读int16
        buffer = self.client.read_area(snap7.types.Areas.DB, self.dbnumber, start, size) # buffer为bytearray
        value_int16 = util.get_int(buffer,0) # 解码为整数
        return value_int16

    def read_bool(self, start=0, size=1) -> int: # 读bool
        buffer = self.client.read_area(snap7.types.Areas.DB, self.dbnumber, start, size)
        value_int16 = util.get_bool(buffer, 0, 0)
        return value_int16

    def read_real(self, start=0, size=4) -> float: # 读实数
        buffer = self.client.read_area(snap7.types.Areas.DB, self.dbnumber, start, size)
        value_real = util.get_real(buffer, 0)
        return value_real


    def write_int8(self, start=0, data_int8=0): # 写int8
        data_bytes = bytearray(1) # 实数4字节
        util.set_byte(data_bytes, 0, data_int8)
        self.client.write_area(snap7.types.Areas.DB, self.dbnumber, start, data_bytes)

    def write_real(self, start=0, data_real=1.0): # 写实数  用于发送坐标等
        data_bytes = bytearray(4) # 实数4字节
        util.set_real(data_bytes, 0, data_real)
        self.client.write_area(snap7.types.Areas.DB, self.dbnumber, start, data_bytes)

    def write_bool(self, start=0, data_bool=False): # 写bool
        data_bytes = bytearray(1)  #
        util.set_bool(data_bytes, 0, 0, data_bool)
        self.client.write_area(snap7.types.Areas.DB, self.dbnumber, start, data_bytes)

    def read_string(self, start=0, size=50, dbnumber=0) -> str: # 读 string  size=256
        buffer = self.client.read_area(snap7.types.Areas.DB, dbnumber, start, size)
        value_str = util.get_string(buffer, 0)
        return value_str

    def write_string(self, start=0, data_str='hello', dbnumber=0): # write string
        data_bytes = bytearray(255) #  ？
        util.set_string(data_bytes, 0, data_str)
        print(data_bytes)
        le = min(len(data_str)+2,50)
        print(data_bytes[:le])
        self.client.write_area(snap7.types.Areas.DB, dbnumber, start, data_bytes[:le]) #size 50

    def read(self):
        '''
        读 （固定 Areas - index , 起始位， 长度 ）
        :return: buffer bytearray
        '''
        buffer = self.client.read_area(snap7.types.Areas.DB, self.dbnumber, 0, 40) # server.register_area(srvAreaDB, 0, DBdata)
        # value = snap7.util.get_real(buffer, 0)
        return buffer

    def write(self, data):
        '''
        写 （固定 Areas - index， 起始位）
        :param data: bytearray or bytes
        :return:
        '''
        # data = bytes([1,2,3,4])
        self.client.write_area(snap7.types.Areas.DB, self.dbnumber, 0, data)
        return None

    def close(self):
        self.client.disconnect()
        print(f"plc 连接状态：{self.client.get_connected()}")

def test0():
    # 建立模拟服务端
    # python D:\soft\Python38\Lib\site-packages\snap7\server\__main__.py
    from snap7 import util
    # 建立客户端
    cl = S7Client('192.168.0.1',  102)
    # cl = S7Client()
    cl.connect()

    # 写
    # data = bytes([1,2,3,4])
    data = bytearray(4)
    util.set_real(data,0, 12.345)
    cl.write(data)

    # 读
    out_data = cl.read()

    rea = util.get_real(out_data, 4)
    print(rea)
    # print
    print(out_data)
    # import struct
    # struct.u
    for i in range(0,len(out_data)):
        print(out_data[i])

    cl.close()


def test_s7client():
    from snap7 import util
    # 建立客户端
    cl = S7Client('192.168.0.1',  102)
    # cl = S7Client()
    cl.connect()
    cl2 = S7Client('192.168.0.1',  102)
    # cl = S7Client()
    cl2.connect()

    # data = cl.read_bool(start=80.1)
    # cl.write_bool(start=96,data_bool=True)

    # data = cl.read_int8(start=97)
    cl.write_int8(start=90,data_int8=6)

    # print(data)
    cl.close()


if __name__ == "__main__":
    test_s7client()